home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / libpq / be-pqexec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  8.7 KB  |  388 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    be-pqexec.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    support for executing POSTGRES commands and functions
  7.  *    from a user-defined function in a backend.
  8.  *
  9.  *   INTERFACE ROUTINES
  10.  *     PQfn         - call a POSTGRES function
  11.  *     PQexec         - execute a POSTGRES query
  12.  *    
  13.  *   NOTES
  14.  *    These routines are compiled into the postgres backend.
  15.  *
  16.  *   IDENTIFICATION
  17.  *    $Header: /private/postgres/src/lib/libpq/RCS/be-pqexec.c,v 1.10 1992/06/28 03:49:07 mao Exp $
  18.  * ----------------------------------------------------------------
  19.  */
  20.  
  21. #include "tmp/postgres.h"
  22.  
  23. RcsId ("$Header: /private/postgres/src/lib/libpq/RCS/be-pqexec.c,v 1.10 1992/06/28 03:49:07 mao Exp $");
  24.  
  25. #include "nodes/pg_lisp.h"
  26. #include "tcop/dest.h"
  27. #include "tmp/fastpath.h"
  28. #include "tmp/simplelists.h"
  29. #include "tmp/libpq-be.h"
  30. #include "utils/exception.h"
  31. #include "utils/builtins.h"
  32. #include "utils/log.h"
  33.  
  34. /* ----------------------------------------------------------------
  35.  *            PQ interface routines
  36.  * ----------------------------------------------------------------
  37.  */
  38.  
  39. /* ----------------
  40.  *    PQfn -  Send a function call to the POSTGRES backend.
  41.  *
  42.  *    fnid        : function id
  43.  *     result_buf      : pointer to result buffer (&int if integer)
  44.  *     result_len    : length of return value.
  45.  *     result_is_int    : If the result is an integer, this must be non-zero
  46.  *     args        : pointer to a NULL terminated arg array.
  47.  *              (length, if integer, and result-pointer)
  48.  *     nargs        : # of arguments in args array.
  49.  *
  50.  *    This code scavanged from HandleFunctionRequest() in tcop/fastpath.h
  51.  * ----------------
  52.  */
  53. char *
  54. PQfn(fnid, result_buf, result_len, result_is_int, args, nargs)
  55.     int fnid;
  56.     int *result_buf;    /* can't use void, dec compiler barfs */
  57.     int result_len;
  58.     int result_is_int;
  59.     PQArgBlock *args;
  60.     int nargs;
  61. {
  62.     char *retval;        /* XXX - should be datum, maybe ? */
  63.     int  arg[8];
  64.     int  rettype;
  65.     int  i;
  66.     
  67.     /* ----------------
  68.      *    fill args[] array
  69.      * ----------------
  70.      */
  71.     for (i = 0; i < nargs; i++) {
  72.     if (args[i].len == VAR_LENGTH_ARG) {
  73.         arg[i] = (int) args[i].u.ptr;
  74.     } else if (args[i].len > 4)  {
  75.         elog(WARN,"arg_length of argument %d too long",i);
  76.     } else {
  77.         arg[i] = args[i].u.integer;
  78.     }
  79.     }
  80.     
  81.     /* ----------------
  82.      *    call the postgres function manager
  83.      * ----------------
  84.      */
  85.     retval = (char *)
  86.     fmgr(fnid, arg[0], arg[1], arg[2], arg[3],
  87.          arg[4], arg[5], arg[6], arg[7]);
  88.     
  89.     /* ----------------
  90.      *    put the result in the buffer the user specified and
  91.      *  return the proper code.
  92.      * ----------------
  93.      */
  94.     if (rettype == 0)        /* void retval */
  95.     return "0";
  96.     
  97.     if (result_is_int) {
  98.     *(int *)result_buf = (int) retval;
  99.     } else {
  100.     bcopy(retval, result_buf, result_len);
  101.     }
  102.     return "G";
  103. }
  104.  
  105. /* ----------------
  106.  *    PQexec -  Send a query to the POSTGRES backend
  107.  *
  108.  *     The return value is a string.  
  109.  *     If 0 or more tuples fetched from the backend, return "P portal-name".
  110.  *     If a query is does not return tuples, return "C query-command".
  111.  *     If there is an error: return "E error-message".
  112.  *
  113.  *    Note: if we get a serious error or an elog(WARN), then PQexec never
  114.  *    returns because the system longjmp's back to the main loop.
  115.  * ----------------
  116.  */
  117.  
  118. char *
  119. PQexec(query)
  120.     char *query;
  121. {
  122.     PortalEntry *entry = NULL;
  123.     char *result = NULL;
  124.  
  125.     /* ----------------
  126.      *    create a new portal and put it on top of the portal stack.
  127.      * ----------------
  128.      */
  129.     entry = (PortalEntry *) be_newportal();
  130.     be_portalpush(entry);
  131.     
  132.     /* ----------------
  133.      *    pg_eval_dest will put the query results in a portal which will
  134.      *  end up on the top of the portal stack.
  135.      * ----------------
  136.      */
  137.     pg_eval_dest(query, (char *) NULL, (ObjectId *) NULL, 0, Local);
  138.     
  139.     /* ----------------
  140.      *    pop the portal off the portal stack and return the
  141.      *  result.  Note if result is null, we return E.
  142.      * ----------------
  143.      */
  144.     entry = (PortalEntry *) be_portalpop();
  145.     result = entry->result;
  146.     if (result == NULL) {
  147.     char *PQE = "Enull PQexec result";
  148.     result = strcpy(palloc(strlen(PQE)), PQE);
  149.     }
  150.     
  151.     return result;
  152. }
  153.  
  154. /* ----------------------------------------------------------------
  155.  *            pqtest support
  156.  * ----------------------------------------------------------------
  157.  */
  158.  
  159. /* ----------------
  160.  *    pqtest_PQexec takes a text query and returns the number of
  161.  *    tuples it returns.  Note: there is no need to PQclear()
  162.  *    here - the memory will go away at end transaction.
  163.  * ----------------
  164.  */
  165. int
  166. pqtest_PQexec(q)
  167.     char      *q;
  168. {
  169.     PortalBuffer *a;
  170.     char      *res;
  171.     int      t;
  172.  
  173.     /* ----------------
  174.      *    execute the postgres query
  175.      * ----------------
  176.      */
  177.     res = PQexec(q);
  178.  
  179.     /* ----------------
  180.      *    return number of tuples in portal or 0 if command returns no tuples.
  181.      * ----------------
  182.      */
  183.     t = 0;
  184.     switch(res[0]) {
  185.     case 'P':
  186.     a = PQparray(&res[1]);
  187.     if (a == NULL)
  188.         elog(WARN, "pqtest_PQexec: PQparray could not find portal %s",
  189.          res);
  190.     
  191.     t = PQntuples(a);
  192.     break;
  193.     case 'C':
  194.     break;
  195.     default:
  196.     elog(NOTICE, "pqtest_PQexec: PQexec(%s) returns %s", q, res);
  197.     break;
  198.     }
  199.     
  200.     return t;
  201. }
  202.  
  203. /* ----------------
  204.  *    utilities for pqtest_PQfn()
  205.  * ----------------
  206.  */
  207.   
  208. char *
  209. strmake(str, len)
  210.     char *str;
  211.     int len;
  212. {
  213.     char *newstr;
  214.     if (str == NULL) return NULL;
  215.     if (len <= 0) len = strlen(str);
  216.     
  217.     newstr = (char *) palloc((unsigned) len+1);
  218.     (void) strncpy(newstr, str, len);
  219.     newstr[len] = (char) 0;
  220.     return newstr;
  221. }
  222.  
  223. #define SKIP 0
  224. #define SCAN 1
  225.  
  226. static char spacestr[] = " ";
  227.  
  228. int
  229. strparse(s, fields, offsets, maxfields)
  230.     char *s;
  231.     char **fields;
  232.     int *offsets;
  233.     int maxfields;
  234. {
  235.     int len = strlen(s);
  236.     char *cp = s, *end = cp + len, *ep;
  237.     int parsed = 0;
  238.     int mode = SKIP, i = 0;
  239.  
  240.     if (*(end - 1) == '\n') end--;
  241.  
  242.     for (i=0; i<maxfields; i++)
  243.     fields[i] = spacestr;
  244.  
  245.     i = 0;
  246.     while (!parsed) {
  247.     if (mode == SKIP) {
  248.         
  249.         while ((cp < end) &&
  250.            (*cp == ' ' || *cp == '\t'))
  251.            cp++;
  252.         if (cp < end) mode = SCAN;
  253.         else parsed = 1;
  254.         
  255.     } else {
  256.         
  257.         ep = cp;
  258.         while ((ep < end) && (*ep != ' ' && *ep != '\t'))
  259.            ep++;
  260.         
  261.         if (ep < end) mode = SKIP;
  262.         else parsed = 1;
  263.         
  264.         fields[i] = strmake(cp, ep - cp);
  265.         if (offsets != NULL)
  266.            offsets[i] = cp - s;
  267.  
  268.         i++;
  269.         cp = ep;
  270.         if (i > maxfields)
  271.            parsed = 1;
  272.         
  273.     }
  274.     }
  275.     return i;
  276. }
  277.  
  278. /* ----------------
  279.  *    pqtest_PQfn converts it's string into a PQArgBlock and
  280.  *    calls the specified function, which is assumed to return
  281.  *    an integer value.
  282.  * ----------------
  283.  */
  284. int
  285. pqtest_PQfn(q)
  286.     char      *q;
  287. {
  288.     int k, j, i, v, f, offsets;
  289.     char *fields[8];
  290.     PQArgBlock pqargs[7];
  291.     int res;
  292.     char *pqres;
  293.     
  294.     /* ----------------
  295.      *    parse q into fields
  296.      * ----------------
  297.      */
  298.     i = strparse(q, fields, &offsets, 8);
  299.     printf("pqtest_PQfn: strparse returns %d fields\n", i); /* debug */
  300.     if (i == 0)
  301.     return -1;
  302.     
  303.     /* ----------------
  304.      *    get the function id
  305.      * ----------------
  306.      */
  307.     f = atoi(fields[0]);
  308.     printf("pqtest_PQfn: func is %d\n", f); /* debug */
  309.     if (f == 0)
  310.     return -1;
  311.     
  312.     /* ----------------
  313.      *    build a PQArgBlock
  314.      * ----------------
  315.      */
  316.     for (j=1; j<i && j<8; j++) {
  317.     k = j-1;
  318.     v = atoi(fields[j]);
  319.     if (v != 0 || (v == 0 && fields[j][0] == '0')) {
  320.         pqargs[k].len = 4;
  321.         pqargs[k].u.integer = v;
  322.         printf("pqtest_PQfn: arg %d is int %d\n", k, v); /* debug */
  323.     } else {
  324.         pqargs[k].len = VAR_LENGTH_ARG;
  325.         pqargs[k].u.ptr = (int *) textin(fields[j]);
  326.         printf("pqtest_PQfn: arg %d is text %s\n", k, fields[j]); /*debug*/
  327.     }
  328.     }
  329.  
  330.     /* ----------------
  331.      *    call PQfn
  332.      * ----------------
  333.      */
  334.     pqres = PQfn(f, &res, 4, 1, pqargs, i-1);
  335.     printf("pqtest_PQfn: pqres is %s\n", pqres); /* debug */
  336.     
  337.     /* ----------------
  338.      *    free memory used
  339.      * ----------------
  340.      */
  341.     for (j=0; j<i; j++) {
  342.     pfree(fields[j]);
  343.     if (pqargs[j].len == VAR_LENGTH_ARG)
  344.         pfree(pqargs[j].u.ptr);
  345.     }
  346.     
  347.     /* ----------------
  348.      *    return result
  349.      * ----------------
  350.      */
  351.     printf("pqtest_PQfn: res is %d\n", res); /* debugg */
  352.     return res;
  353. }
  354.  
  355. /* ----------------
  356.  *    pqtest looks at the first character of it's test argument
  357.  *    and decides which of pqtest_PQexec or pqtest_PQfn to call.
  358.  * ----------------
  359.  */
  360.  
  361. int32
  362. pqtest(vlena)
  363.     struct varlena    *vlena;
  364. {
  365.     PortalBuffer *a;
  366.     char      *q;
  367.     char      *res;
  368.     int      t;
  369.  
  370.     /* ----------------
  371.      *    get the query
  372.      * ----------------
  373.      */
  374.     q = textout(vlena);
  375.     if (q == NULL)
  376.     return -1;
  377.     
  378.     switch(q[0]) {
  379.     case '%':
  380.     return pqtest_PQfn(&q[1]);
  381.     break;
  382.     default:
  383.     return pqtest_PQexec(q);
  384.     break;
  385.     }
  386.     return(0);
  387. }
  388.